#import <Accelerate/Accelerate.h>
#import "UIImage+Extension.h"

typedef struct {
	UInt8		r;
	UInt8		g;
	UInt8		b;
	UInt8		a;
} COLORPIXEL;

/*===================================================================
 说明:
	填充指定颜色(可以渐变)的当前路径
 ==================================================================*/
static void CGContextFillPathWithColor(CGContextRef ctx, CGRect rc, id color)
{
	if (!color) return;
	
	if ([color isKindOfClass:[UIColor class]])
	{
		CGContextSetFillColorWithColor(ctx, [color CGColor]);
		CGContextFillRect(ctx, rc);
	}
	else if ([color isKindOfClass:[NSArray class]])		//填充渐变色
	{
		CGPoint endPoint = CGPointMake(rc.origin.x, CGRectGetMaxY(rc));
		[UIView drawLinearGradient:ctx colors:color startPoint:rc.origin endPoint:endPoint];
	}
}

/*===================================================================
 图像扩展
 ==================================================================*/
@implementation UIImage (Extension)
+ (UIImage *)imageForColor:(UIColor *)color
{
	return [UIImage imageForColor:color size:CGSizeMake(1, 1)];
}
+ (UIImage *)imageForColor:(UIColor *)color size:(CGSize)size
{
	UIGraphicsBeginImageContextWithOptions(size, NO, 0);
	
	CGContextRef ctx = UIGraphicsGetCurrentContext();
	CGContextSetFillColorWithColor(ctx, color.CGColor);
	CGContextFillRect(ctx, CGRectMake(0, 0, size.width, size.height));
	
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	return image;
}

#pragma mark - 获取视图图像
/*===================================================================
 说明:
	获取视图图像
 ==================================================================*/
+ (UIImage *)imageForView:(UIView *)view
{
	return [UIImage imageForView:view background:nil];
}

+ (UIImage *)imageForView:(UIView *)view background:(id)background
{
	return [UIImage imageForView:view background:background overlay:nil];
}

+ (UIImage *)imageForView:(UIView *)view background:(id)background overlay:(id)overlay
{
	UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
	CGRect rect = {CGPointZero, view.bounds.size};
	
	//背景
	if ([background isKindOfClass:[UIColor class]])
	{
		CGContextRef ctx = UIGraphicsGetCurrentContext();
		CGContextSetFillColorWithColor(ctx, [background CGColor]);
		CGContextFillRect(ctx, rect);
	}
	else if ([background isKindOfClass:[UIImage class]])
	{
		[background drawInRect:rect];
	}
	
	//截图
	//[view.layer renderInContext:UIGraphicsGetCurrentContext()];
	[view drawViewHierarchyInRect:rect afterScreenUpdates:NO];
	
	//覆盖
	if ([overlay isKindOfClass:[UIColor class]])
	{
		CGContextRef ctx = UIGraphicsGetCurrentContext();
		CGContextSetFillColorWithColor(ctx, [overlay CGColor]);
		CGContextFillRect(ctx, rect);
	}
	else if ([overlay isKindOfClass:[UIImage class]])
	{
		[overlay drawInRect:rect];
	}
	
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	view.layer.contents = nil;
	return image;
}

/*===================================================================
 说明:
	获取完整表格视图的图像
 ==================================================================*/
+ (UIImage *)imageForTableView:(UITableView *)tableView background:(id)background
{
	UIGraphicsBeginImageContextWithOptions(tableView.contentSize, NO, 0);
	
	CGPoint origin = tableView.contentOffset;
	
	if ([background isKindOfClass:[UIColor class]])
	{
		CGContextRef ctx = UIGraphicsGetCurrentContext();
		CGContextSetFillColorWithColor(ctx, [background CGColor]);
		CGContextFillRect(ctx, (CGRect){CGPointZero, tableView.contentSize});
	}
	else if ([background isKindOfClass:[UIImage class]])
	{
		[background drawInRect:(CGRect){CGPointZero, tableView.contentSize}];
	}
	
	for (int s=0; s<tableView.numberOfSections; s++)
	{
		for (int r=0; r<[tableView numberOfRowsInSection:s]; r++)
		{
			NSIndexPath *indexPath = [NSIndexPath indexPathForRow:r inSection:s];
			CGRect frame = [tableView rectForRowAtIndexPath:indexPath];
			[tableView scrollRectToVisible:frame animated:NO];
			
			UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
			
			/*UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0);
			[cell.layer renderInContext:UIGraphicsGetCurrentContext()];
			
			UIImage *subImage = UIGraphicsGetImageFromCurrentImageContext();
			UIGraphicsEndImageContext();
			
			[subImage drawInRect:frame];*/
			[cell drawViewHierarchyInRect:frame afterScreenUpdates:NO];
			cell.layer.contents = nil;
		}
	}
	
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	[tableView setContentOffset:origin animated:NO];
	return image;
}

#pragma mark - 转换
/*===================================================================
 说明:
	转换
 ==================================================================*/
- (UIImage *)clipToRect:(CGRect)rect
{
	UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
	
	[self drawAtPoint:CGPointMake(-rect.origin.x, -rect.origin.y)];
	
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	return image;
}

//会铺满然后居中
- (UIImage *)resizeToSize:(CGSize)size
{
	return [self roundedWithSize:size radius:0];
}

- (UIImage *)resizeToScale:(CGFloat)scale
{
	CGRect rect = CGRectMake(0, 0, lrintf(self.size.width * scale), lrintf(self.size.height * scale));
	
	UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
	[self drawInRect:rect];
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	return image;
}

- (UIImage *)rotationToAngle:(CGFloat)angle
{
	return self;
}

- (UIImage *)mirroredAtYAxis:(BOOL)yAxis
{
	UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
	CGContextRef ctx = UIGraphicsGetCurrentContext();

	CGContextScaleCTM(ctx, yAxis ? 1 : -1, yAxis ? -1 : 1);
	CGContextTranslateCTM(ctx, yAxis ? 0 : -self.size.width, yAxis ? -self.size.height : 0);
	
	[self drawInRect:(CGRect){CGPointZero, self.size}];
	
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	return image;
}

- (UIImage *)resizableWithCapInsets:(UIEdgeInsets)insets
{
	return [self resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch];
}

#pragma mark - 圆角
/*===================================================================
 说明:
	圆角矩形
 ==================================================================*/
- (UIImage *)roundWithSize:(CGSize)size
{
	return [self roundedWithSize:size radius:-1];
}

- (UIImage *)roundedWithSize:(CGSize)size radius:(CGFloat)radius;
{
	return [self roundedWithSize:size radius:radius borderColor:nil borderWidth:0];
}

- (UIImage *)roundedWithSize:(CGSize)size radius:(CGFloat)radius borderColor:(UIColor *)color borderWidth:(CGFloat)width
{
	if (CGSizeEqualToSize(size, CGSizeZero)) size = self.size;
	
	UIGraphicsBeginImageContextWithOptions(size, NO, 0);
	CGContextRef ctx = UIGraphicsGetCurrentContext();
	
	if (radius == -1) radius = MIN(size.width, size.height) / 2.f;
	
	CGRect frame = CGRectMake(0, 0, size.width, size.height);
	
	if (radius)
	{
		[[UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:radius] addClip];
	}
	
	if (width && color)		//边框
	{
		radius *= 1.f - width * 2.f / MIN(size.width, size.height);
		size.width -= width * 2.f;
		size.height -= width * 2.f;
		
		CGContextSetFillColorWithColor(ctx, color.CGColor);
		CGContextFillRect(ctx, frame);
		
		frame = CGRectInset(frame, width, width);
		[[UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:radius] addClip];
	}
	
	//等比例缩放
	CGFloat sr = self.size.width / self.size.height;
	CGFloat sd = size.width / size.height;
	
	if (sr > sd)
	{
		frame.size.width  = floorf(size.width * sr / sd / 2);
		frame.origin.x += floorf((size.width - frame.size.width) / 2.f);
	}
	else if (sr < sd)
	{
		frame.size.height = floorf(size.height * sr / sd);
		frame.origin.y += floorf((size.height - frame.size.height) / 2.f);
	}
	
	[self drawInRect:frame];
	
	//生成图像
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return image;
}

#pragma mark - Gradient
/*===================================================================
 说明:
	Gradient
 ==================================================================*/
- (UIImage *)gradientWithColors:(NSArray <__kindof UIColor *> *)colors orientation:(UIInterfaceOrientation)orientation
{
	CGPoint startPoint = CGPointZero;
	CGPoint endPoint = UIInterfaceOrientationIsPortrait(orientation) ? CGPointMake(0, self.size.height) : CGPointMake(self.size.width, 0);
	
	if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationLandscapeLeft)
		return [self gradientWithColors:colors startPoint:startPoint endPoint:endPoint];
	else
		return [self gradientWithColors:colors startPoint:endPoint endPoint:startPoint];
}

- (UIImage *)gradientWithColors:(NSArray <__kindof UIColor *> *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint
{
	UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
	CGContextRef ctx = UIGraphicsGetCurrentContext();
	
	[UIView drawLinearGradient:ctx colors:colors startPoint:startPoint endPoint:endPoint];
	
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return image;
}

#pragma mark - 图像处理
/*===================================================================
 说明:
	图像去色
 ==================================================================*/
- (UIImage *)grayImage
{
	return [self processingWithStyle:UIImageProcessingStyleGray];
}

/*===================================================================
 说明:
	图像上色
 ==================================================================*/
- (UIImage *)tintColor:(id)tintColor
{
	return [self tintColor:tintColor capInsets:UIEdgeInsetsZero];
}

- (UIImage *)tintColor:(id)tintColor capInsets:(UIEdgeInsets)insets
{
	UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
	
	CGContextRef context = UIGraphicsGetCurrentContext();
	CGContextTranslateCTM(context, 0, self.size.height);
	CGContextScaleCTM(context, 1.0, -1.0);
	CGContextSetBlendMode(context, kCGBlendModeNormal);
	
	CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
	CGContextClipToMask(context, rect, self.CGImage);
	
	CGContextFillPathWithColor(context, rect, tintColor);
	
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	
	UIGraphicsEndImageContext();
	
	if (UIEdgeInsetsEqualToEdgeInsets(insets, UIEdgeInsetsZero))
		return newImage;
	else
		return [newImage resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch];
}

/*===================================================================
 说明:
	图像处理
 ==================================================================*/
- (UIImage *)processingWithStyle:(UIImageProcessingStyle)style
{
	size_t width  = CGImageGetWidth(self.CGImage);
	size_t height = CGImageGetHeight(self.CGImage);
	size_t bitsPerComponent = CGImageGetBitsPerComponent(self.CGImage);
	size_t bitsPerPixel = CGImageGetBitsPerPixel(self.CGImage);
	size_t bytesPerRow = CGImageGetBytesPerRow(self.CGImage);
	
	// 画像のデータプロバイダを取得する
	CGDataProviderRef dataProvider = CGImageGetDataProvider(self.CGImage);
	
	// データプロバイダから画像のbitmap生データ取得
	CFDataRef   data = CGDataProviderCopyData(dataProvider);
	UInt8*		buffer = (UInt8*)CFDataGetBytePtr(data);
	
	// 1ピクセルずつ画像を処理
	for (uint y = 0; y < height; y++)
	{
		COLORPIXEL *clr = (COLORPIXEL *)(buffer + y * bytesPerRow);
		
		for (uint x = 0; x < width; x++)
		{
			switch (style)
			{
				case UIImageProcessingStyleGray:	//去色（灰度）
					clr->r = clr->g = clr->b = (77 * clr->r + 28 * clr->g + 151 * clr->b) / 256;
					break;
					
				case UIImageProcessingStyleInvert:	//反转颜色
					if (clr->a)
					{
						clr->r = 255 - clr->r;
						clr->g = 255 - clr->g;
						clr->b = 255 - clr->b;
					}
					break;
					
				case UIImageProcessingStyleBrown:	//棕褐色
					clr->g = clr->g * 0.7;
					clr->b = clr->b * 0.4;
					break;
			}
			
			clr ++;
		}
	}
	
	CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
	CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(self.CGImage);
	
	// 画像がピクセル間の補完をしているか
	bool shouldInterpolate = CGImageGetShouldInterpolate(self.CGImage);
	
	// 表示装置によって補正をしているか
	CGColorRenderingIntent intent = CGImageGetRenderingIntent(self.CGImage);
	
	// 効果を与えたデータ生成
	CFDataRef effectedData = CFDataCreate(NULL, buffer, CFDataGetLength(data));
	
	// 効果を与えたデータプロバイダを生成
	CGDataProviderRef effectedDataProvider = CGDataProviderCreateWithCFData(effectedData);
	
	// 画像を生成
	CGImageRef effectedCgImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow,
									colorSpace, bitmapInfo, effectedDataProvider, NULL, shouldInterpolate, intent);
	
	UIImage *effectedImage = [[UIImage alloc] initWithCGImage:effectedCgImage];
	
	// データの解放
	CGImageRelease(effectedCgImage);
	CFRelease(effectedDataProvider);
	CFRelease(effectedData);
	CFRelease(data);
	
	return effectedImage;
}

#pragma mark - 高斯模糊
/*===================================================================
 说明:
	高斯模糊图像
 ==================================================================*/
- (UIImage *)blurWithRadius:(CGFloat)radius
{
	return [self blurWithRadius:radius tintColor:nil];
}

- (UIImage *)blurWithRadius:(CGFloat)radius tintColor:(id)tintColor
{
	return [self fastBlurWithRadius:radius tintColor:tintColor];
	//return [self systemBlurWithRadius:radius tintColor:tintColor];
}

/*===================================================================
 说明:
	异步模糊
 ==================================================================*/
- (void)asyncBlurWithRadius:(CGFloat)radius tintColor:(id)tintColor handler:(void (^)(UIImage *))handler
{
	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
		UIImage *image = [self blurWithRadius:radius tintColor:tintColor];
		dispatch_async(dispatch_get_main_queue(), ^{if (handler) handler(image);});
	});
}

/*===================================================================
 说明:
	模糊图像(使用系统滤镜)
 ==================================================================*/
- (UIImage *)systemBlurWithRadius:(CGFloat)radius tintColor:(UIColor *)tintColor
{
	CIContext *context = [CIContext contextWithOptions:nil];
	CIImage *inputImage = [CIImage imageWithCGImage:self.CGImage];
	
	CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
	[filter setValue:inputImage forKey:kCIInputImageKey];
	[filter setValue:@(radius) forKey:@"inputRadius"];
	
	CIImage *result = [filter valueForKey:kCIOutputImageKey];
	CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]];
	UIImage *blurImage = [UIImage imageWithCGImage:cgImage];
	CGImageRelease(cgImage);
	
	UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
	
	[blurImage drawInRect:CGRectInset(CGRectMake(0, 0, self.size.width, self.size.height), radius, radius)];
	
	//
	CGRect rc = CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale);
	CGContextFillPathWithColor(UIGraphicsGetCurrentContext(), rc, tintColor);
	
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	return image;
}

/*===================================================================
 说明:
	模糊图像(高效， box模糊效果没高斯好)
 ==================================================================*/
- (UIImage *)fastBlurWithRadius:(CGFloat)radius tintColor:(id)tintColor
{
	CGDataProviderRef dataProvider = CGImageGetDataProvider(self.CGImage);
	
	CFDataRef inBitmapData = CGDataProviderCopyData(dataProvider);
	size_t bitsPerComponent = CGImageGetBitsPerComponent(self.CGImage);
	
	vImage_Buffer inBuffer, outBuffer, tmpBuffer;
	inBuffer.data = (void *)CFDataGetBytePtr(inBitmapData);
	inBuffer.width = CGImageGetWidth(self.CGImage);
	inBuffer.height = CGImageGetHeight(self.CGImage);
	inBuffer.rowBytes = CGImageGetBytesPerRow(self.CGImage);
	
	outBuffer = inBuffer;
	tmpBuffer = inBuffer;
	outBuffer.data = malloc(inBuffer.rowBytes * inBuffer.height);
	tmpBuffer.data = malloc(inBuffer.rowBytes * inBuffer.height);
	
	//box三次模糊
	int boxSize = (int)lrintf(radius * 5);
	boxSize -= (boxSize % 2) + 1;
	vImageBoxConvolve_ARGB8888(&inBuffer,  &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
	vImageBoxConvolve_ARGB8888(&outBuffer, &tmpBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
	vImageBoxConvolve_ARGB8888(&tmpBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
	
	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
	
	//iOS截图与保存的位图信息不到致，分别处理
	CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(self.CGImage);
	CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(self.CGImage);
	
	switch ((int)alphaInfo)
	{
		case kCGImageAlphaLast:
		case kCGImageAlphaNoneSkipLast:
			bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
			break;
			
		case kCGImageAlphaFirst:
		case kCGImageAlphaNoneSkipFirst:
			bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;
	}
	
	CGContextRef ctx = CGBitmapContextCreate(outBuffer.data, outBuffer.width, outBuffer.height, bitsPerComponent, outBuffer.rowBytes, colorSpace, bitmapInfo);
	
	//填充色
	CGRect rc = CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale);
	CGContextFillPathWithColor(ctx, rc, tintColor);
	
	CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
	UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
	CGImageRelease(imageRef);
	
	CGColorSpaceRelease(colorSpace);
	free(outBuffer.data);
	free(tmpBuffer.data);
	CFRelease(inBitmapData);
	CGContextRelease(ctx);
	
	return returnImage;
}

@end
